package com.cctc.rds.scheduler.core.task;

import java.util.HashMap;
import java.util.Map;

/**
 * 任务实例工厂。
 * 任务实例唯一标识：所在命名空间（app） +（::） 任务名称（taskName）。
 * 前提：需要提前将任务类型或任务实例放入任务实例工厂。
 * - 如果工厂中没有任务实例，则根据任务类型反射生成一个任务实例；
 * - 如果工厂中存在任务实例，则直接返回。
 * - 如果工厂中存在多个相同标识的任务类型或任务实例，则返回最后放入的任务实例。
 */
public class TaskFactory {
    private static final Map<String, Class<? extends Task<?>>> TASK_CLASS_MAP = new HashMap<>();
    private static final Map<String, Task<?>> TASK_MAP = new HashMap<>();
    private static Object LOCK = new Object();

    private static String getTaskKey(String app, String taskName) {
        return app + "::" + taskName;
    }

    public static void putTaskClass(String app, String taskName, Class<? extends Task<?>> taskClass) {
        String taskKey = getTaskKey(app, taskName);
        synchronized (LOCK) {
            if (TASK_CLASS_MAP.containsKey(taskKey)) {
                TASK_CLASS_MAP.replace(taskKey, taskClass);
            } else {
                TASK_CLASS_MAP.put(taskKey, taskClass);
            }
        }
    }

    public static <T extends Task<?>> void putTask(String app, String taskName, T task) {
        String taskKey = getTaskKey(app, taskName);
        synchronized (LOCK) {
            if (TASK_MAP.containsKey(taskKey)) {
                TASK_MAP.replace(taskKey, task);
            } else {
                TASK_MAP.put(taskKey, task);
            }
        }
    }

    public static Task<?> getTask(String app, String taskName) {
        String taskKey = getTaskKey(app, taskName);
        Task<?> task = TASK_MAP.get(taskKey);
        if (task == null) {
            try {
                Class<? extends Task<?>> taskClass = TASK_CLASS_MAP.get(taskKey);
                task = taskClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return task;
    }

}
